﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RaytheonTimeWindows.Properties;
using RaytheonTimeDataModel;

namespace RaytheonTimeWindows
{
    public partial class frmEditWorkday : Form
    {
        #region Private Data Members

        private Workday workday_;
        private bool isSaved_ = false;
        private bool isNew_ = true;
        private int workdayId_ = 0;
        private RaytheonTimeDataEntities db_;
        private double workHours_ = 0.0; 

        private BindingList<Worktime> worktimeBindingList_;

        #endregion

        #region Public Data Members

        public Common.DataChangedDelegate DataChangedCallback;

        #endregion

        #region Constructors

        public frmEditWorkday()
        {
            InitializeComponent();
            Init();

            try
            {
                workdayId_ = 0;
                isSaved_ = false;
            }
            catch (Exception ex)
            {
                String message = "Error occurred converting calling Workday Constructor\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public frmEditWorkday(Int32 workdayId)
        {
            InitializeComponent();
            Init();

            try
            {
                isNew_ = false;
                workdayId_ = workdayId;
                isSaved_ = true;
            }
            catch (Exception ex)
            {
                String message = "Error occurred converting calling Workday Constructor\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Overriden Event Handlers

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                LoadData();
            }
            catch (Exception ex)
            {
                String message = "Error occurred converting calling Loading frmEditWorkday\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            try
            {
                if (!isSaved_)
                {
                    DialogResult dgResult;
                    dgResult = MessageBox.Show("Record not saved; are you sure you want to exit?",
                                               "Unsaved Record Warning", MessageBoxButtons.YesNo,
                                               MessageBoxIcon.Warning);
                    if (dgResult == DialogResult.No)
                    {
                        e.Cancel = true;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Closing\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Private Event Handlers

        private void frmEditWorkday_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Escape)
                {
                    this.Close();
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Pressing the Escape Key\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                Save();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                RefreshForm();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Refreshing\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnEdit_Click(object sender, EventArgs e)
        {
            try
            {
                CheckIfModified();
                if (!isSaved_)
                {
                    if (!Save())
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            try
            {
                EditWorktime();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Double Clicking a cell\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnNew_Click(object sender, EventArgs e)
        {
            try
            {
                CheckIfModified();
                if (!isSaved_)
                {
                    if (!Save())
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                frmEditWorktime form = new frmEditWorktime(workday_.workdayId, workday_.workdayDate, workday_.employeeId);
                form.DataChangedCallback = new Common.DataChangedDelegate(this.UpdateDataCallback);
                form.Show();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Newing Worktime\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void dgvWorktimes_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                CheckIfModified();
                if (!isSaved_)
                {
                    if (!Save())
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            try
            {
                EditWorktime();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Double Clicking a cell\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                if (dgvWorktimes.SelectedRows.Count == 1)
                {
                    DeleteRow();
                }
                else
                {
                    MessageBox.Show("You must select a row before clicking Delete", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Deleting Worktime\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void dgvWorktimes_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Delete)
                {
                    if (dgvWorktimes.SelectedRows.Count == 1)
                    {
                        DeleteRow();
                    }
                    else
                    {
                        MessageBox.Show("You must select a row before clicking Delete", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Pressing the Delete Key\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSummary_Click(object sender, EventArgs e)
        {
            try
            {
                Common.DisplaySummary(workdayId_);
            }
            catch (Exception ex)
            {
                String message = "Error occurred clicking on Summary\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void dgvWorktimes_MouseDown(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    var hti = dgvWorktimes.HitTest(e.X, e.Y);
                    dgvWorktimes.ClearSelection();
                    dgvWorktimes.Rows[hti.RowIndex].Selected = true;
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred clicking mouse button on the workday grid\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void editToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                CheckIfModified();
                if (!isSaved_)
                {
                    if (!Save())
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            try
            {
                EditWorktime();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Double Clicking a cell\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                if (dgvWorktimes.SelectedRows.Count == 1)
                {
                    DeleteRow();
                }
                else
                {
                    MessageBox.Show("You must select a row before clicking Delete", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Deleting Worktime\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void summaryToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                Common.DisplaySummary(workdayId_);
            }
            catch (Exception ex)
            {
                String message = "Error occurred clicking on Summary\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Private Members

        private void Init()
        {
            if (db_ != null)
            {
                db_.Dispose();
            }
            db_ = new RaytheonTimeDataEntities();
        }

        private void LoadData()
        {
            Init();
            if (workdayId_ > 0)
            {
                workday_ = (from b in db_.Workdays
                            where b.workdayId == workdayId_ &&
                                  b.isDeleted == false
                            select b).FirstOrDefault();

                txtWorkdayId.Text = workday_.workdayId.ToString();
                txtEmployeeId.Text = workday_.Employee.employeeNumber.Trim();
                txtHours.Text = workday_.hours.ToString("#.00");
                if (workday_.workdayDate > DateTimePicker.MinimumDateTime)
                {
                    dtpDate.Value = workday_.workdayDate;
                }
                else
                {
                    dtpDate.Value = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
                }
                LoadWorktime();
            }
            else
            {
                workday_ = new Workday();

                txtWorkdayId.Text = String.Empty;
                txtEmployeeId.Text = String.Empty;
                txtHours.Text = "0.00";
                dtpDate.Value = DateTime.Now;
                LoadWorktime();
            }

            ToggleControls();
        }

        private void ToggleControls()
        {
            btnEdit.Enabled = isSaved_ ? dgvWorktimes.RowCount > 0 : false;
            btnNew.Enabled = isSaved_;
        }

        private void LoadWorktime()
        {
            var worktimes = workday_.Worktimes.OrderBy(e => e.timeStart);

            worktimeBindingList_ = new BindingList<Worktime>(worktimes.ToList());
            dgvWorktimes.DataSource = worktimeBindingList_;

            int rowIndex = 0;

            foreach (var worktime in worktimes)
            {
                // time End
                dgvWorktimes.Rows[rowIndex].Cells[2].Value = worktime.timeStart.AddMinutes(worktime.duration * 60.0).ToString("HH:mm");

                ++rowIndex;
            }

            dgvWorktimes.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }

        private void EditWorktime()
        {
            try
            {
                if (dgvWorktimes.SelectedRows.Count == 1)
                {
                    Int32 worktimeId = Convert.ToInt32(dgvWorktimes.SelectedRows[0].Cells[0].Value);
                    frmEditWorktime form = new frmEditWorktime(worktimeId);
                    form.DataChangedCallback = new Common.DataChangedDelegate(this.UpdateDataCallback);
                    form.Show();
                }
                else
                {
                    MessageBox.Show("You must select a row before clicking Edit", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Editing Worktime\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private bool Save()
        {
            bool isValid = true;

            try
            {
                using (var db = new RaytheonTimeDataEntities())
                {
                    String employeeNumber = txtEmployeeId.Text.Trim();
                    var employee = (from e in db.Employees
                                    where String.Compare(e.employeeNumber, employeeNumber, true) == 0 &&
                                          e.isDelete == false
                                    select e).FirstOrDefault();

                    if (employee == null)
                    {
                        employee = new Employee();
                        employee.employeeNumber = employeeNumber;
                        db.Employees.Add(employee);
                        db.SaveChanges();
                    }

                    workday_.employeeId = employee.employeeId;
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving Employee\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                isValid = false;
            }

            try
            {
                workday_.workdayDate = new DateTime(dtpDate.Value.Year, dtpDate.Value.Month, dtpDate.Value.Day);
            }
            catch (Exception ex)
            {
                String message = "Error occurred setting Date\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                isValid = false;
            }

            // uniqueness test
            try
            {
                using (var db = new RaytheonTimeDataEntities())
                {
                    var workday = (from d in db.Workdays
                                   where d.employeeId == workday_.employeeId &&
                                         d.workdayDate == workday_.workdayDate &&
                                         d.workdayId != workday_.workdayId &&
                                         d.isDeleted == false
                                   select d).FirstOrDefault();
                    if (workday != null)
                    {
                        String message = "A record with this date already exists, please select another date.";
                        MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        isValid = false;
                    }
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred checking uniqueness\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                isValid = false;
            }

            try
            {
                if (isValid)
                {
                    if (isNew_)
                    {
                        db_.Workdays.Add(workday_);
                    }

                    db_.SaveChanges();

                    // Refresh the database context
                    db_.Dispose();
                    db_ = new RaytheonTimeDataEntities();

                    workday_ = (from w in db_.Workdays
                                where w.workdayId == workday_.workdayId
                                select w).FirstOrDefault();

                    workdayId_ = workday_.workdayId;
                    DataChangedCallback();
                    isSaved_ = true;
                    isNew_ = false;
                    LoadData();
                    RefreshForm();
                    return true;
                }
            }
            catch (Exception ex)
            {
                String message = "Error occurred Saving\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return false;
        }

        private void RefreshForm()
        {
            try
            {
                dgvWorktimes.Rows.Clear();
                LoadData();
                ToggleControls();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Refreshing Datagrid\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CheckIfModified()
        {
            if (workday_.Employee != null && !workday_.Employee.employeeNumber.Trim().Equals(txtEmployeeId.Text.Trim(), StringComparison.CurrentCultureIgnoreCase))
            {
                isSaved_ = false;
            }
            if (workday_.workdayDate != null && (workday_.workdayDate.Year != dtpDate.Value.Year ||
                                                 workday_.workdayDate.Month != dtpDate.Value.Month ||
                                                 workday_.workdayDate.Day != dtpDate.Value.Day))
            {
                isSaved_ = false;
            }
        }

        private void UpdateDataCallback()
        {
            try
            {
                // update current form
                RefreshForm();
                // update parent form
                DataChangedCallback();
            }
            catch (Exception ex)
            {
                String message = "Error occurred Updating Data Callback (refresh)\n";
                message += ex.Message;
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void DeleteRow()
        {
            DialogResult dr = MessageBox.Show("Are you sure you and to delete the selected row?", "Delete Confirmation",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == System.Windows.Forms.DialogResult.Yes)
            {
                Int32 worktimeId = Convert.ToInt32(dgvWorktimes.SelectedRows[0].Cells[0].Value);
                var worktime = (from w in db_.Worktimes
                                where w.worktimeId == worktimeId &&
                                      w.isDeleted == false
                                select w).FirstOrDefault();
                worktime.isDeleted = true;
                db_.SaveChanges();
                dgvWorktimes.Rows.Clear();
                RefreshForm();
            }
        }

        #endregion
    }
}
